using Network.Delegate;
using Network.Tcp.Awaitable;
using Network.Tcp.Pooling;
using Network.Tcp.NetSession;
using Network.Tcp.TcpConfig;
using Network.UtilityHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Network.Tcp
{
    public abstract class NetEngineBased
    {
        private static readonly byte[] EmptyArray = new byte[0];
        protected readonly List<Session> _sessions = new List<Session>(); //SESSION列表
        protected readonly ConfigBase _cfg;
        protected readonly AwaiterPool _awaiterPool = new AwaiterPool();
        protected readonly SessionPool _sessionPool = new SessionPool();
        protected readonly LogHelper _logger = new LogHelper();
        protected NotifyEventHandler<CompleteNotify, Session> _completetionNotify;
        protected SessionType _SessionType;

        //当前SESSION数量
        public int SessionCount
        {
            get { return _sessions.Count; }
        }
        #region 构造函数
        internal NetEngineBased(
            SessionType sessionType,
            ConfigBase cfg,
            NotifyEventHandler<CompleteNotify, Session> completetionNotify)
        {
            _SessionType = sessionType;
            _cfg = cfg;
            _completetionNotify = completetionNotify;
            Awaiter createMethod() => new Awaiter();
            void cleanMethod(Awaiter sArg)
            {
                try
                {
                    sArg.Args.AcceptSocket = null;
                    sArg.Args.SetBuffer(EmptyArray, 0, EmptyArray.Length);
                    sArg.Args.RemoteEndPoint = null;
                    sArg.Args.SocketFlags = SocketFlags.None;
                }
                catch (Exception ex)
                {
                    _logger.WriteLog("server_clean awaiter info：" + ex.Message);
                    Console.WriteLine(ex.Message);
                }
            }
            //初始化awaiterPool
            _awaiterPool.Initialize(createMethod, cleanMethod, 50);
            if (sessionType == SessionType.Full)
            {
                _sessionPool.Initialize(() => new FullSessionBased(_cfg, _awaiterPool, _sessionPool, completetionNotify, _logger, this),
                    (session) =>
                    {
                        session.Detach();
                    }, 50);
            }
            else
            {
                _sessionPool.Initialize(() => new PackSessionBased(_cfg, _awaiterPool, _sessionPool, completetionNotify, _logger, this),
                    (session) =>
                    {
                        session.Detach();
                    }, 50);
            }
        }
        #endregion
        public abstract void Broadcast(byte[] data);
        public abstract void Broadcast(byte[] data, int offset, int length);
        public abstract void ClearConnections(bool notify);
        public abstract void Dispose();
    }
}
